package com.mikelouis.test.scala.proginscala.chapter19

/**
 * Created by yuazhu on 1/26/2015.
 */
object FinalFunctionalQueue {
  def main(args: Array[String]) {
    println("************ improved functional queue ***************")
    val queue = new FinalFunctionalQueue[Int](List(1), List(2))
    println(queue)
    val queue2 = queue.append(3)
    println(queue2)
    val queue3 = queue2.append('c')
    println(queue3)
  }
}

/**
 * improved functional queue
 * if private[this] is omitted will throw compile error
 * Error:(207, 9) covariant type T occurs in contravariant position in type List[T] of value leading_=
 * class FinalFunctionalQueue[+T] private(private var leading: List[T], private var trailing: List[T]) {
 *      ^
 * @param leading
 * @param trailing
 * @tparam T
 */
class FinalFunctionalQueue[+T] private(private[this] var leading: List[T], private[this] var trailing: List[T]) {
  private def mirror() =
    if (leading.isEmpty) {
      while (!trailing.isEmpty) {
        leading = trailing.head :: leading
        trailing = trailing.tail
      }
    }

  def head: T = {
    mirror()
    leading.head
  }

  def tail: FinalFunctionalQueue[T] = {
    mirror()
    new FinalFunctionalQueue(leading.tail, trailing)
  }

  def append[U >: T](x: U) = new FinalFunctionalQueue[U](leading, x :: trailing)

  override def toString = leading ::: trailing.reverse mkString("FinalFunctionalQueue(", ", ", ")")
}
